package com.itstherules.jmsunit.mock.activemq;

import static com.itstherules.jmsunit.JmsUnit.sender;
import static com.itstherules.jmsunit.JmsUnit.mock;
import static com.itstherules.jmsunit.expectation.Expectations.headers;
import static com.itstherules.jmsunit.expectation.XmlBasedExpectations.xPathDoesntExist;
import static com.itstherules.jmsunit.expectation.XmlBasedExpectations.xPathEq;

import org.junit.Before;
import org.junit.Test;

import com.itstherules.jmsunit.JmsInlineMock;
import com.itstherules.jmsunit.JmsSender;
import com.itstherules.jmsunit.managers.QueueManagersFactory.QueueManagerType;

public class JmsXPathExpectationTest {

	private static String fullXml = "<root>" + "<shoot>" + "<abba/>"
			+ "<acdc></acdc>" + "<eno>eno</eno>" + "</shoot>" + "<boot>"
			+ "<UNKLE>UNKLEMix</UNKLE>" + "<lfo>lowFrequencyOscillation</lfo>"
			+ "<soundgarden>superunknown</soundgarden>" + "</boot>" + "</root>";

	private JmsInlineMock stub;

	private JmsSender sender;

	@Before
	public void create() throws Exception {
		stub = mock("vm://localhost:61616", QueueManagerType.ActiveMQ);
		sender = sender("blue", "vm://localhost:61616",
				QueueManagerType.ActiveMQ);
	}

	@Test
	public void xPathEqualsFullXmlAllPresentAndMore() throws Exception {
		stub.expects().through("blue").with(xPathEq("eno", "/root/shoot/eno"))
				.with(xPathEq("UNKLEMix", "/root/boot/UNKLE")).with(
						xPathEq("superunknown", "/root/boot/soundgarden"));

		sender.send(fullXml, headers("Blue2"));
		stub.verifyAndClose();
	}

	@Test(expected = IllegalArgumentException.class)
	public void xPathEqualsFullXmlInvalidXpath() throws Exception {
		stub.expects().through("blue")
				.with(xPathEq("", "sdf/as?|+-@q23sef\\d"));

		sender.send(fullXml, headers("Blue2"));
		stub.verifyAndClose();
	}

	@Test(expected = IllegalArgumentException.class)
	public void xPathEqualsFullXmlXPathNotFoundAndExpectedNull()
			throws Exception {
		stub.expects().through("blue").with(xPathEq(null, "/rot/sdf"));

		sender.send(fullXml, headers("Blue2"));
		stub.verifyAndClose();
	}

	@Test(expected = AssertionError.class)
	public void xPathEqualsFullXmlXPathNotFound() throws Exception {
		stub.expects().through("blue").with(xPathEq("asa", "/rot/sdf"));

		sender.send(fullXml, headers("Blue2"));
		stub.verifyAndClose();
	}

	@Test(expected = IllegalArgumentException.class)
	public void xPathEqualsFullXmlXPathNotFoundLeafAndExpectedNull()
			throws Exception {
		stub.expects().through("blue").with(xPathEq(null, "/root/shoot/hd"));

		sender.send(fullXml, headers("Blue2"));
		stub.verifyAndClose();
	}

	@Test
	public void xPathEqualsFullXmlEmptyValueClosedTag() throws Exception {
		stub.expects().through("blue").with(xPathEq("", "/root/shoot/abba"));

		sender.send(fullXml, headers("Blue2"));
		stub.verifyAndClose();
	}

	@Test
	public void xPathEqualsFullXmlEmptyValueEmptyString() throws Exception {
		stub.expects().through("blue").with(xPathEq("", "/root/shoot/acdc"));

		sender.send(fullXml, headers("Blue2"));
		stub.verifyAndClose();
	}

	@Test
	public void xPathEqualsFullXmlAllPresentStrict() throws Exception {
		stub.expects().through("blue").with(xPathEq("eno", "/root/shoot/eno"))
				.with(xPathEq("UNKLEMix", "/root/boot/UNKLE"))
				.with(xPathEq("soundgardenmessage", "/root/boot/soundgarden"));

		sender.send("<root>" + "<shoot>" + "<eno>eno</eno>" + "</shoot>"
				+ "<boot>" + "<UNKLE>UNKLEMix</UNKLE>"
				+ "<soundgarden>soundgardenmessage</soundgarden>" + "</boot>"
				+ "</root>", headers("Blue2"));
		stub.verifyAndClose();
	}

	@Test(expected = AssertionError.class)
	public void xPathEqualsFailureOneNotPresentHC() throws Exception {
		stub.expects().through("blue").with(xPathEq("eno", "/root/shoot/eno"))
				.with(xPathEq("UNKLE", "/root/boot/UNKLE")).with(
						xPathEq("soundgarden", "/root/boot/soundgarden"));

		sender.send("<root>" + "<shoot>" + "<abba/>" + "<acdc></acdc>"
				+ "</shoot>" + "<boot>" + "<UNKLE>UNKLEMix</UNKLE>"
				+ "<lfo>lowFrequencyOscillation</lfo>"
				+ "<soundgarden>soundgardenmessage</soundgarden>" + "</boot>"
				+ "<root>", headers("Blue2"));
		stub.verifyAndClose();
	}

	@Test(expected = AssertionError.class)
	public void xPathEqualsFailureOneNotPresentBA() throws Exception {
		stub.expects().through("blue").with(xPathEq("eno", "/root/shoot/eno"))
				.with(xPathEq("UNKLE", "/root/boot/UNKLE")).with(
						xPathEq("soundgarden", "/root/boot/soundgarden"));

		sender.send("<root>" + "<shoot>" + "<abba/>" + "<acdc></acdc>"
				+ "<eno>eno</eno>" + "</shoot>" + "<boot>"
				+ "<lfo>lowFrequencyOscillation</lfo>"
				+ "<soundgarden>soundgardenmessage</soundgarden>" + "</boot>"
				+ "<root>", headers("Blue2"));
		stub.verifyAndClose();
	}

	@Test(expected = AssertionError.class)
	public void xPathEqualsFailureOneNotPresentBC() throws Exception {
		stub.expects().through("blue").with(xPathEq("eno", "/root/shoot/eno"))
				.with(xPathEq("UNKLE", "/root/boot/UNKLE")).with(
						xPathEq("soundgarden", "/root/boot/soundgarden"));

		sender.send("<root>" + "<shoot>" + "<abba/>" + "<acdc></acdc>"
				+ "<eno>eno</eno>" + "</shoot>" + "<boot>"
				+ "<UNKLE>UNKLEMix</UNKLE>"
				+ "<lfo>lowFrequencyOscillation</lfo>" + "</boot>" + "<root>",
				headers("Blue2"));
		stub.verifyAndClose();
	}

	@Test
	public void xPathNullStandalone() throws Exception {
		stub.expects().through("blue").with(xPathDoesntExist("/root/shoot/hd"));

		sender.send(fullXml, headers("Blue2"));
		stub.verifyAndClose();
	}

	@Test(expected = IllegalArgumentException.class)
	public void xPathNullInvalidXpath() throws Exception {
		stub.expects().through("blue").with(
				xPathDoesntExist("sdf/as?|+-@q23sef\\d"));

		sender.send(fullXml, headers("Blue2"));
		stub.verifyAndClose();
	}

	@Test
	public void xPathNullXPathNotFound() throws Exception {
		stub.expects().through("blue").with(xPathDoesntExist("/rot/sdf"));

		sender.send(fullXml, headers("Blue2"));
		stub.verifyAndClose();
	}

	@Test(expected = AssertionError.class)
	public void xPathNullExisits() throws Exception {
		stub.expects().through("blue").with(
				xPathDoesntExist("/root/shoot/abba"));

		sender.send(fullXml, headers("Blue2"));
		stub.verifyAndClose();
	}

	@Test(expected = AssertionError.class)
	public void xPathNullEmptyString() throws Exception {
		stub.expects().through("blue").with(
				xPathDoesntExist("/root/shoot/acdc"));

		sender.send(fullXml, headers("Blue2"));
		stub.verifyAndClose();
	}

	@Test(expected = AssertionError.class)
	public void xPathNullValueExists() throws Exception {
		stub.expects().through("blue")
				.with(xPathDoesntExist("/root/shoot/eno"));

		sender.send(fullXml, headers("Blue2"));
		stub.verifyAndClose();
	}

	@Test(expected = IllegalArgumentException.class)
	public void xPathNullNullXPath() throws Exception {
		stub.expects().through("blue").with(xPathDoesntExist(null));

		sender.send(fullXml, headers("Blue2"));
		stub.verifyAndClose();
	}

}
